package com.utils;

import javax.servlet.http.HttpServletRequest;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

public class BeanUtils {

    private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");

    public static <T> T processParamters(HttpServletRequest request,Class<T> targetClass) throws InstantiationException, IllegalAccessException, IntrospectionException, ParseException, InvocationTargetException {
        //要求请求参数的名字必须和对象的属性名保持一致
        //实际上我们的操作就是获取到每一个参数,然后根据参数名找到类中的 set 方法,然后把参数的值设置过去\
        //比如 我们找到了 username 这个参数,要从类中找 setUsername()
        Enumeration<String> parameterNames = request.getParameterNames();//获取所有参数名
        T instance = targetClass.newInstance();//反射创建对象
        while (parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();//获取每一个参数名
            String value = request.getParameter(name);//获取这个参数对应的值
            if("option".equals(name)){
                continue;

            }
            //从指定类中找当前遍历到的参数名对应的属性描述
            PropertyDescriptor propertyDescriptor=new PropertyDescriptor(name,targetClass);
            if(propertyDescriptor!=null){
                //找到这个属性了
                Method writeMethod = propertyDescriptor.getWriteMethod();//set方法
                if(writeMethod!=null){
                    Class<?>[] parameterTypes = writeMethod.getParameterTypes();//获取set方法参数类型
                    if(parameterTypes.length>0){
                        Class<?>parameterType=parameterTypes[0];//获取具体的方法参数
                        if(parameterType== Date.class){
                            //因为字节码文件只有一份,所以不管怎么获取都是一份 class,所以在这里可以通过==来判断 class
                            Date date = simpleDateFormat.parse(value);
                            //有set方法
                            writeMethod.invoke(instance,date);//将值设置过去
                            continue;//跳出当前循环，继续下一个循环

                        }
                        //String类型可以直接赋值
                        if(parameterType==String.class){
                            //有set方法
                            writeMethod.invoke(instance,value);
                            continue;

                        }
                        if(parameterType==Integer.class||parameterType==int.class){
                            try {
                                int i = Integer.parseInt(value);
                                writeMethod.invoke(instance,i);//将值设置过去
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                            continue;

                        }
                        if(parameterType==Long.class||parameterType==long.class){
                            try {
                                long i = Long.parseLong(value);
                                writeMethod.invoke(instance,i);//将值设置过去
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                            continue;

                        }
                    }

                }


            }


        }
        return instance;

    }
}
